#pragma once

#include <map>
#include <boost/shared_ptr.hpp>

#include <ace/ACE.h>
#include <ace/Task.h>
#include <ace/OS.h>

//#include <ace/Thread.h>
//#include <ace/Mutex.h>

#include "../../Common/Util/Logger.h"
#include "../../Common/Util/Singulator.h"
#include "../../Common/Util/Timer.h"

#include "NxPhysics.h"
#include "PhysicsObject.h"
#include "PhysicsLocale.h"

#pragma comment(lib, "PhysXLoader.lib")

#define DISPLAY_PHYSICS_BODIES 1
#define BOUNCINESS 0.2f
#define SPHERE_RADIUS 1.0f
namespace Physics
{
	

	// Physics Engine = THREAD
	class PhysicsEngine : public ACE_Task<ACE_MT_SYNCH>
	{
		friend PhysicsLocale;	
	private:
		long long	m_nextObjectIdAvailable;
		long long	m_nextLocaleIdAvailable;


	protected:
		
		// We use 2 map structurs to hold the physics objects and terrain objects.
		std::map<long long, boost::shared_ptr<PhysicsLocale>>  m_physicsLocales; 
		std::map<long long, boost::shared_ptr<PhysicsObject>>  m_physicsObjects; 
		ACE_Recursive_Thread_Mutex                         m_mutex;
		NxSceneDesc m_sceneDesc;
		NxPhysicsSDK*	m_PhysicsSDK;
		
				
		// Benchmark class used for internal timing.
		Tool::Bench m_timer;

		// Time since last update.
		double m_elapsedtime;
		
		bool m_bQuit;
		bool m_bPause;

		bool InitialiseAgeia();
		void updateWorld(float p_steptime);
		void cleanup();
	public:
		PhysicsEngine();
		~PhysicsEngine();

		// This is the main() function for the thread.
		int		svc();
		void quit();
		void pause() { m_bPause = true;}
		void unpause() { m_bPause = false;}
		float m_updatetime;

		long long createLocale();
		void destroyLocale(long long p_localeid);
		PhysicsLocale* getLocale(long long p_localeid);

		long long createObject();
		void destroyObject(long long p_objectid);
		PhysicsObject* getObject(long long p_objectid);


	};
};
